using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using System.Web;
using System.Security.Permissions;
using Telerik.Web.UI;
using System.Collections;
using System.Reflection;

namespace DataExchange
{
   
    public class GenericControl : CompositeControl 
    {
        #region Variables
        private RadGrid gvSource;
        private RadGrid gvDestination;
        private UpdatePanel updatePanel;
        private Button btnTransfer;
        private Button btnTransferBack;

        public delegate void OnTransferOccured(object transferedEntity,TransferDirection direction );
        public event OnTransferOccured Transfer;
        
        #endregion

        #region Properties

        [PersistenceMode(PersistenceMode.InnerProperty)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public FiledsCollection FieldsCollection { get; set; }

        public string Name { get; set; }
        
        public bool AutoGenerateColumns { get; set; }

        public int PageSize { get; set; }

        public int CurrentPageIndex 
        {

            get
            {
                if (Page.Session["CurrentPageIndex"] != null)
                    return int.Parse(Page.Session["CurrentPageIndex"].ToString());

                return 0;
            }
            set
            {
                Page.Session["CurrentPageIndex"] = value;
            }
        }

        public bool AllowPaging { get; set; }

        public bool AllowSorting { get; set; }

        public string DataKeyNames { get; set; }

        public IEnumerable<object> SourceDataSource
        {
            get
            {
                if (Page.Session["SourceDataSource"] == null)
                    throw new Exception("Data source is null");

                return (IEnumerable<object>)Page.Session["SourceDataSource"];
            }
            set
            {
                Page.Session["SourceDataSource"] = value;
            }
        }

        public IEnumerable<object> DestinationDataSource
        {
            get
            {
                return (IEnumerable<object>)Page.Session["DestinationDataSource"];

            }
            set
            {
                Page.Session["DestinationDataSource"] = value;

            }
        }

      
       
        #endregion

        #region Methods

        #region DataSource

        private static object LoadData(object data)
        {
            return data;
        }

        public object GetSourceDataSource()
        {
            return gvSource.DataSource;
        }

        public void SetSourceDataSource(object dataSource)
        {

            gvSource.DataSource = dataSource;
            gvSource.DataBind();
         

        }

        public IEnumerable<object> GetDestinationDataSource()
        {

            return DestinationDataSource;

        }


        #endregion

        #region Events

        #region Page Events

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

          

        }

        protected override void CreateChildControls()
        {

            Controls.Clear();

          
            gvSource = new RadGrid();

            gvDestination = new RadGrid();

            btnTransfer = new Button();
            btnTransfer.Text = ">";
            btnTransfer.Click += new EventHandler(btnTransfer_Click);

            updatePanel = new UpdatePanel();

            btnTransferBack = new Button();
            btnTransferBack.Text = "<";
            btnTransferBack.Enabled = false;
            btnTransferBack.Click += new EventHandler(btnTransferBack_Click);


            updatePanel.ContentTemplateContainer.Controls.Add(gvSource);
            updatePanel.ContentTemplateContainer.Controls.Add(gvDestination);
            updatePanel.ContentTemplateContainer.Controls.Add(btnTransferBack);
            updatePanel.ContentTemplateContainer.Controls.Add(btnTransfer);
            updatePanel.UpdateMode = UpdatePanelUpdateMode.Always;
            updatePanel.ChildrenAsTriggers = true;

        
            
            gvSource.PageIndexChanged += new GridPageChangedEventHandler(gvSource_PageIndexChanged);
            gvSource.NeedDataSource += new GridNeedDataSourceEventHandler(gvSource_NeedDataSource);
            gvSource.AllowPaging = (this.PageSize > 0) ? true : false;
            gvSource.PageSize = this.PageSize;
            gvSource.AutoGenerateColumns = this.AutoGenerateColumns;
            gvSource.AllowMultiRowSelection = true;
            gvSource.Width = this.Width;
            gvSource.CssClass="DataExSourceGrid";
            gvSource.PagerStyle.Mode = GridPagerMode.NumericPages;
            gvSource.PagerStyle.ShowPagerText = false;
            gvSource.MasterTableView.NoMasterRecordsText = "Must be Localized to OSD";
           
            GenerateGridColumns(FieldsCollection, gvSource);


            gvDestination.CssClass = "DataExDestinationGrid";
            gvDestination.Width = this.Width;
            gvDestination.AutoGenerateColumns = this.AutoGenerateColumns;
            gvDestination.MasterTableView.NoMasterRecordsText = "Must be Localized to OSD";

            GenerateGridColumns(FieldsCollection, gvDestination);


            this.Controls.Add(updatePanel);

            this.Controls.Add(gvSource);

            this.Controls.Add(gvDestination);

            this.Controls.Add(btnTransfer);

            this.Controls.Add(btnTransferBack);



        }

      

        

        void gvSource_NeedDataSource(object source, GridNeedDataSourceEventArgs e)
        {

            if (GetSourceDataSource() == null)
            {
                gvSource.DataSource = SourceDataSource;
             
            }   
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
        }

      
        protected override void Render(HtmlTextWriter writer)
        {


            AddAttributesToRender(writer);

            updatePanel.RenderControl(writer);

            writer.RenderBeginTag(HtmlTextWriterTag.Table);
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            gvSource.RenderControl(writer);
            writer.RenderEndTag();
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            writer.RenderBeginTag(HtmlTextWriterTag.Table);
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            btnTransfer.RenderControl(writer);
            writer.RenderEndTag();
            writer.RenderEndTag();
            writer.RenderBeginTag(HtmlTextWriterTag.Tr);
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            btnTransferBack.RenderControl(writer);
            writer.RenderEndTag();
            writer.RenderEndTag();
            writer.RenderEndTag();
            writer.RenderEndTag();
            writer.RenderBeginTag(HtmlTextWriterTag.Td);
            gvDestination.RenderControl(writer);
            writer.RenderEndTag();
            writer.RenderEndTag();
            writer.RenderEndTag();

            
        }

        #endregion

        #region Control Events
      

        protected void btnTransfer_Click(object sender, EventArgs e)
        {
            if (gvSource.SelectedItems!=null && gvSource.SelectedItems.Count != 0)
            {

                IEnumerable<object> TransferedItems;


                if (DestinationDataSource == null)
                    DestinationDataSource = new List<object>();

                TransferedItems = Search(gvSource,SourceDataSource);
                DestinationDataSource = Enumerable.Concat(DestinationDataSource, TransferedItems);
                gvDestination.DataSource = DestinationDataSource;
                gvDestination.DataBind();


                SourceDataSource= Enumerable.Except(SourceDataSource, DestinationDataSource);
                gvSource.DataSource = SourceDataSource;
                gvSource.DataBind();


                OnTransfer_EventHandler(TransferedItems, TransferDirection.Forward);

            }
        }

        private IEnumerable<object> Search(RadGrid control,IEnumerable<object> dataSource)
        {
            IEnumerable<object> newDataSource=null;
            foreach (object x in dataSource)
            {

                foreach (PropertyInfo field in x.GetType().GetProperties())
                {
                    if (control.MasterTableView.DataKeyNames.Contains(field.Name) == true && field.GetValue(x, null).Equals(control.SelectedValue))
                    {

                        newDataSource = (from t in dataSource where t.Equals(x) select t).AsEnumerable();

                        return newDataSource;

                    }

                }
            }
            return newDataSource;
            
        }

        private void SetDestinationDataSource(IEnumerable<object> dataSource)
        {
            gvDestination.DataSource = dataSource;
            gvDestination.DataBind();
            DestinationDataSource = dataSource;
        }


        void btnTransferBack_Click(object sender, EventArgs e)
        {
            if (gvDestination.SelectedItems != null && gvDestination.SelectedItems.Count != 0)
            {

                IEnumerable<object> TransferedItems;

                TransferedItems = Search(gvDestination, DestinationDataSource);
                SourceDataSource = Enumerable.Concat(SourceDataSource, TransferedItems);
                gvSource.DataSource = SourceDataSource;
                gvSource.DataBind();


                DestinationDataSource = Enumerable.Except(DestinationDataSource, SourceDataSource);
                gvDestination.DataSource = DestinationDataSource;
                gvDestination.DataBind();


                OnTransfer_EventHandler(TransferedItems, TransferDirection.Backward);

            }
        }


        void gvSource_PageIndexChanged(object source, GridPageChangedEventArgs e)
        {
            if (GetSourceDataSource() == null)
                SetSourceDataSource(SourceDataSource);

            gvSource.CurrentPageIndex = e.NewPageIndex;

            gvSource.Rebind();

        }


        #endregion
       
        #endregion

        #region Common Methods

        private void GenerateGridColumns(FiledsCollection FieldsCollection, RadGrid grid)
        {

            grid.MasterTableView.DataKeyNames = DataKeyNames.Split(new char[] { ',' });

          GridButtonColumn selectButton=new GridButtonColumn();

            selectButton.Text="Select";

            selectButton.CommandName="Select";

            grid.Columns.Add(selectButton);

            

            if (this.AutoGenerateColumns==false)
            {

                foreach (Field field in FieldsCollection)
                {

                    switch (field.Type)
                    {

                        default:
                        case Types.String:
                            GridBoundColumn boundColumn = new GridBoundColumn();
                            boundColumn.HeaderText = field.HeaderText;
                            boundColumn.DataType = Type.GetType("System.String");
                            boundColumn.DataField = field.DataField;
                            grid.Columns.Add(boundColumn);


                            break;

                        case Types.Number:
                            GridNumericColumn numericColumn = new GridNumericColumn();
                            numericColumn.HeaderText = field.HeaderText;
                            numericColumn.DataType = Type.GetType("System.Int32");
                            numericColumn.DataField = field.DataField;


                            grid.Columns.Add(numericColumn);


                            break;

                        case Types.DateTime:
                            GridDateTimeColumn dateTimeColumn = new GridDateTimeColumn();
                            dateTimeColumn.HeaderText = field.HeaderText;
                            dateTimeColumn.DataType = Type.GetType("System.DateTime");
                            dateTimeColumn.DataField = field.DataField;

                            grid.Columns.Add(dateTimeColumn);

                            break;
                    }

                }
            }
        }

        #endregion

        #endregion

        #region Explicit Page Events


        protected virtual void OnTransfer_EventHandler(object obj, TransferDirection direction)
        {

           
                    if (gvSource.Items.Count > 0)
                    {
                        btnTransfer.Enabled = true;
                    }
                    else
                    {
                        btnTransfer.Enabled = false;
                    }

                    if (gvDestination.Items.Count > 0)
                    {
                        btnTransferBack.Enabled = true;
                    }
                    else
                    {
                        btnTransferBack.Enabled = false;
                    }

                

            if (Transfer != null)
                Transfer(obj, direction);
        }

        #endregion

    }
}
